package com.ponhu.ea2.goodsCenter.provider.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ponhu.ea2.common.basic.model.ResponseBean;
import com.ponhu.ea2.constants.CommonConstant;
import com.ponhu.ea2.constants.DictConstant;
import com.ponhu.ea2.dto.LogsForTextAddDto;
import com.ponhu.ea2.dto.PhInventoryBaseDto;
import com.ponhu.ea2.dto.PhInventoryForPurchaseDto;
import com.ponhu.ea2.entity.*;
import com.ponhu.ea2.enums.*;
import com.ponhu.ea2.goodsCenter.provider.biz.InvokeStockCenterInterfaceService;
import com.ponhu.ea2.goodsCenter.provider.biz.OperationRecordLogsCoreService;
import com.ponhu.ea2.goodsCenter.provider.factory.GoodsFactory;
import com.ponhu.ea2.goodsCenter.provider.factory.GoodsFactoryService;
import com.ponhu.ea2.goodsCenter.provider.mapper.InventoryMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.MaterialMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.PhBrandMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.PhSysDictItemMapper;
import com.ponhu.ea2.goodsCenter.provider.utils.CommonUtils;
import com.ponhu.ea2.properties.GoodsProperties;
import com.ponhu.ea2.service.facade.GoodsCenterForPonHuService;
import com.ponhu.ea2.service.facade.GoodsCenterForWMSService;
import com.ponhu.ea2.service.facade.InventoryApiService;
import com.ponhu.ea2.vo.PhInventoryBaseVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * @author luyu
 * @create 2021-11-03 13:42
 */
@Service
@Slf4j
public class PhInventoryForCreateByPurchaseService implements
        GoodsFactoryService<PhInventoryForPurchaseDto> {
    @Resource
    private InvokeStockCenterInterfaceService invokeStockCenterInterfaceService;

    @Resource
    private GoodsCenterForWMSService goodsCenterForWMSService;

    @Resource
    private GoodsCenterForPonHuService goodsCenterForPonHuService;

    @Resource
    private PhBrandMapper phBrandMapper;

    @Resource
    private MaterialMapper materialMapper;

    @Resource
    private PhSysDictItemService phSysDictItemService;

    @Resource
    private InventoryApiService inventoryApiService;

    @Resource
    private OperationRecordLogsCoreService operationRecordLogsCoreService;

    @Resource
    private InventoryMapper inventoryMapper;

    @Resource
    GoodsProperties goodsProperties;

    /**
     * 处理具体的逻辑
     * @param inventoryDto
     * @return
     */
    @Override
    public ResponseBean<PhInventoryBaseVo> createOrUpdateGoods(PhInventoryForPurchaseDto inventoryDto) {
        Inventory inventory = new Inventory();// 货品对象
        Goods goods = new Goods();// 商品对象

        log.info("采购入参为{}",inventoryDto);
        // 校验参数,根据来源
        if(parameterVerification(inventoryDto)){
            return ResponseBean.error("入参数据错误,请校验参数重新提交");
        }
        // 如果是b端采购标品,则校验是否已经创建
        PhInventoryBaseVo phInventoryBaseVo = checkGoodsByMaterialId(inventoryDto);
        if(ObjectUtils.isNotEmpty(phInventoryBaseVo)){
            // 推送胖总管数据
            CompletableFuture.runAsync(() -> {
                inventoryDto.setInventoryCode(phInventoryBaseVo.getInventoryCode());
                inventoryDto.setIsSecondPurchase(true);
                goodsCenterForPonHuService.createGoodsInfoForPonHu(inventoryDto);
            });
            return ResponseBean.ok(phInventoryBaseVo);
        }
        // 组装货品数据,保存到数据库
        processingInventoryData(inventory,goods,inventoryDto);
        // 保存商品信息和货品信息以及商品货品中间表
        Boolean createInventorybool = inventoryApiService.saveInventoryAndGoods(inventory, goods);
        if(!createInventorybool){
            return ResponseBean.error("商品中心保存商品失败");
        }
        // 商品中心保存成功以后,记录日志
        CompletableFuture.runAsync(() ->{
            boolean b = operationRecordLogsCoreService
                    .addTextAddOperationRecordLogs(processingLogData(inventory, inventoryDto));
            if (!b){
                log.error("创建货品记录日志失败,货品id为{},采购渠道为{}",
                        inventory.getId(),inventoryDto.getInventoryChannel());
            }
        });
        // 推送其他中心
        pushOtherCenters(inventoryDto,inventory,goods);
        return ResponseBean.ok(new PhInventoryBaseVo(inventory.getInventoryCode(),
                inventory.getInventoryName()));
    }

    /**
     * 异步推送其他中心商品信息
     * @param inventoryDto
     * @param inventory
     * @param goods
     */
    private void pushOtherCenters(
            PhInventoryForPurchaseDto inventoryDto,
            Inventory inventory,
            Goods goods) {
        // 推送胖总管数据
        CompletableFuture.runAsync(() -> {
            goodsCenterForPonHuService.createGoodsInfoForPonHu(inventoryDto);
        });
        //  调用wms推送商品数据到wms
        CompletableFuture.runAsync(() ->{
            goodsCenterForWMSService.createOrUpdateGoodsForWms(inventory);
        });
        //  对接库存中心,初始化库存
        CompletableFuture.runAsync(() ->{
            invokeStockCenterInterfaceService.createAndInitRealStockData(
                    goods.getId(),inventory.getId(),inventory.getInventoryCode());
        });
    }

    /**
     * 校验b端采购标品的货品是否已经存在
     * @param inventoryDto
     * @return
     */
    private PhInventoryBaseVo checkGoodsByMaterialId(PhInventoryBaseDto inventoryDto) {

        Inventory inventory = null;
        if((InventoryChannelEnum.B_PURCHASE.getCode()).equals(inventoryDto.getInventoryChannel())
                && YesOrNoEnum.NO.getCode().equals(inventoryDto.getIsTwoLuxury())){
            // 根据物料id查询是否有关联的货品,如果有则直接返回
            inventory = inventoryMapper.selectOne(new LambdaQueryWrapper<Inventory>()
                    .eq(Inventory::getMaterialId, inventoryDto.getMaterialId())
                    .eq(Inventory::getIsSecondhand,YesOrNoEnum.NO.getCode()));
        }
        return ObjectUtils.isNotEmpty(inventory)?new PhInventoryBaseVo(
                inventory.getInventoryCode(),
                inventory.getInventoryName()):null;
    }


    /**
     * 根据来源类型校验参数
     * @param inventoryDto
     * @return
     */
    private Boolean parameterVerification(PhInventoryForPurchaseDto inventoryDto) {
        Boolean result = false;
        if(inventoryDto.getInventoryChannel() == null){
            return true;// 货品来源不能为空
        }
        result = parameterVerificationForPurchase(inventoryDto);

        return result;
    }

    private Boolean parameterVerificationForPurchase(PhInventoryForPurchaseDto inventoryDto) {
        if(inventoryDto.getIsTwoLuxury() == null){
            return true;// 是否二奢不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getBrandId())){
            return true;// 品牌id不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getCategoryId())){
            return true;// 商品分类id不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getSourceChannel())){
            return true;// 来源渠道不能为空
        }
        if(inventoryDto.getCoefficient() == null){
            return true;// 渠道系数不能为空
        }
        if(inventoryDto.getPurchasePrice().compareTo(BigDecimal.ZERO) < 1
                || inventoryDto.getPurchasePrice() == null){
            return  true;//采购价不能为空,不能小于0
        }
        if(StringUtils.isBlank(inventoryDto.getWarehousingMethodId())){
            return true;// 入库方式不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getGoodsOwnerId())){
            return true;// 货主不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getFirstProcurementChannel())){
            return true;// 一级采购渠道不能为空
        }
        if(StringUtils.isBlank(inventoryDto.getSecondProcurementChannel())){
            return true;// 二级采购渠道不能为空
        }
        return false;
    }

    // 组装日志信息
    private LogsForTextAddDto processingLogData(Inventory inventory,
                                                PhInventoryForPurchaseDto inventoryDto){
        LogsForTextAddDto logsForTextAddDto = new LogsForTextAddDto();
        logsForTextAddDto.setBusinessTable(CommonConstant.BUSINESS_TYPE_INVENTORY);
        logsForTextAddDto.setRecordId(inventory.getId());
        logsForTextAddDto.setOperator("system");
        logsForTextAddDto.setOperatorId(0L);
        if(inventoryDto.getInventoryChannel()
                == InventoryChannelEnum.CLOUD_TRADE_JOINT_CONSIGNMENT.getCode()){
            logsForTextAddDto.setTextContent("云商系统数据入库");
        }else if ((InventoryChannelEnum.B_PURCHASE.getCode())
                .equals(inventoryDto.getInventoryChannel())){
            logsForTextAddDto.setTextContent("采购中心B端数据入库");
        }else {
            logsForTextAddDto.setTextContent("采购中心C端数据入库");
        }
        return logsForTextAddDto;
    }

    // 组装商品中心的商品和货品数据
    private void processingInventoryData(Inventory inventory,
                                         Goods goods,
                                         PhInventoryForPurchaseDto inventoryDto) {
        // 生成货品编码
        Optional<String> inventoryCode = inventoryApiService.getInventoryCodeByType(
                inventoryDto.getWarehousingMethodId(),
                1,
                ThirdSystemEnum.SYSTEM_PURCHASE,
                inventoryDto.getIsTwoLuxury()).stream().findFirst();
        inventoryDto.setInventoryCode(inventoryCode.get());
        inventory.setInventoryCode(inventoryCode.get());
        LocalDateTime localDateTime = LocalDateTime.now();
        inventory.setInventoryType(InventoryTypeEnum.MAIN_PRODUCT.getCode());// 默认为主品
        inventory.setSalesModel(Integer.parseInt(inventoryDto.getSalesModel()));// 销售模式
        inventory.setIsSecondhand(inventoryDto.getIsTwoLuxury());
        inventory.setSourceChannel(inventoryDto.getSourceChannel());
        inventory.setCreatedTime(localDateTime);
        inventory.setUpdatedTime(localDateTime);
        inventory.setInventoryChannel(inventoryDto.getInventoryChannel());
        inventory.setQuality(Integer.parseInt(inventoryDto.getQuality()));
        PhSysDictItem dictItem = phSysDictItemService.getDictItemByValue(
                DictConstant.CONDITION_TYPE,
                inventoryDto.getQuality());
        inventory.setQualityValue(dictItem.getLabel());
        inventory.setBaseMap(YesOrNoEnum.NO.getCode());
        inventory.setRemarks(inventoryDto.getRemarks());
        inventory.setIsKpi(inventoryDto.getIsKpi());
        if(StringUtils.isNotBlank(inventoryDto.getImages())){
            inventory.setMainImage(inventoryDto.getImages().split("\\|")[0]);
            inventory.setDetailImage(inventoryDto.getImages());
        }
        // 分两种情况,有物料和没有物料
        if(StringUtils.isBlank(inventoryDto.getMaterialId())){
            // 没有物料id的时候,需要采购中心传过来品类和品牌信息
            inventory.setCategoryId(Long.parseLong(inventoryDto.getCategoryId()));
            inventory.setBrandId(Long.parseLong(inventoryDto.getBrandId()));
            PhBrand phBrand = phBrandMapper.selectById(Long.parseLong(inventoryDto.getBrandId()));
            inventory.setInventoryName(dictItem.getLabel()+" "+phBrand.getEnName()
                    +"/"+phBrand.getCnName());//
        }else {
            // 物料不为空的时候
            inventory.setMaterialId(Long.parseLong(inventoryDto.getMaterialId()));
            Material material = materialMapper.selectById(inventoryDto.getMaterialId());
            inventory.setCategoryId(material.getCategoryId());
            inventory.setBrandId(material.getBrandId());
            if(YesOrNoEnum.YES.getCode().equals(inventoryDto.getIsTwoLuxury())){
                inventory.setInventoryName(dictItem.getLabel() +" "+ material.getMaterialName());// 物料名称
            }else {
                inventory.setInventoryName(material.getMaterialName());// 物料名称
            }
        }
        // 如果采购渠道为356,358的时候,根据采购中心传入的渠道,判断是否需要填充
        // 货品成本=采购价*渠道系数+采购价  四舍五入取整数
        /*if(goodsProperties.getErpChannelMap()
                .containsKey(inventoryDto.getErpChannelId())){
            inventory.setInventoryCost(inventoryDto.getPurchasePrice());
            inventory.setWarehousePrice(inventoryDto.getPurchasePrice());
            goods.setSaleTaxPrice(inventoryDto.getSalePrice());
            goods.setSupplyTaxPrice(inventoryDto.getSalePrice());
        }else {*/
            inventory.setInventoryCost(inventoryDto.getPurchasePrice()
                    .multiply(new BigDecimal(inventoryDto.getCoefficient()))
                    .add(inventoryDto.getPurchasePrice())
                    .setScale(2,BigDecimal.ROUND_DOWN));
        //}
        // 封装商品数据
        goods.setGoodsCode(CommonUtils.createGoodsCode());
        goods.setType(GoodsTypeEnum.MATERIAL_OBJECT.getCode());
        goods.setGoodsName(inventory.getInventoryName());
        goods.setGoodsStatus(GoodsStatusEnum.ON_SHELF.getCode());
        goods.setCreatedTime(localDateTime);
        goods.setUpdatedTime(localDateTime);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        GoodsFactory.setMap(this);
    }
}
